﻿namespace EggOfPanKu.Library.Objects
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    using System.ComponentModel;
    
    using Library.Infrastructure;

    [DataObject(true)]
    public static class CardDatabase
    {
        #region Fields

        private static Dictionary<string, Card> _cardDictionary = new Dictionary<string, Card>();

        #endregion Fields

        #region Properties


        public static Dictionary<string, Card> Cards
        {
            get
            {
                return _cardDictionary;
            }
        }

        #endregion Properties

        #region Methods

        //Return some object that will represent all Cards, and all card type values.  This can then be bound to
        //for the DeckBuilder grids.
        public static IEnumerable<Card> GetAllCards(Dictionary<string, Card> _cardDB)
        {
            return from selectCard in _cardDB
                   select selectCard.Value;
        }


        [DataObjectMethod(DataObjectMethodType.Select, true)]
        public static List<Card> GetAllCards(string sortType, int startRowIndex, int MaximumRows)
        {
            var cards = from selectCard in Cards
                        select selectCard.Value;
            cards = cards.Skip(startRowIndex).Take(MaximumRows);
            cards = SortList(cards.AsQueryable<Card>(), sortType);
            return cards.ToList();
        }

        public static int GetCardCount()
        {
            return CardCount;
        }

        private static IQueryable<Card> SortList(IQueryable<Card> cards, string sortType)
        {
            bool sortDesc = false;
            if (!string.IsNullOrEmpty(sortType))
            {
                string[] values = sortType.Split(' ');
                sortType = values[0];
                if (values.Length > 1)
                {
                    sortDesc = values[1] == "DESC";
                }
            }

            switch (sortType)
            {
                case "Name":
                    cards = cards.OrderBy(p => p.Name);
                    break;
                case "Edition":
                    cards = cards.OrderBy(p => p.Edition);
                    break;
                case "CardTypeName":
                    cards = cards.OrderBy(p => p.CardTypeName);
                    break;
                default:
                    cards = cards.OrderBy(p => p.Name);
                    break;
            }
            if (sortDesc)
            {
                cards = cards.Reverse();
            }
            
            return cards;
        }

        public static IEnumerable<Card> GetCardByName(Dictionary<string, Card> _cardDB, string cardName)
        {
            return from selectCard in _cardDB
                   where selectCard.Value.Name.ToString() == cardName
                   select selectCard.Value;
        }
        public static bool isLoaded
        {
            get
            {
                return (CardCount > 0);
            }
        }

        public static int CardCount
        {
            get
            {
                return Cards.Count;
            }
        }
        public static Dictionary<string, Card> LoadCardDatabase(string FileName)
        {
            XElement xDoc = XElement.Load(FileName);
            //XmlDocument xDoc = new XmlDocument();
            //xDoc.Load(FileName);
            Cards.Clear();
            int docNum = 0;
            IEnumerable<XElement> xList = xDoc.Elements("card").ToList();
               
            foreach(XElement c in xList) 
            {
                try
                {
                    Card newCard = CreateNewCardObject(c);
                    if (newCard != null)
                    {
                        Cards.Add(c.Attribute("id").Value, newCard);
                    }
                    else
                    {
                        LogManager.Write(LogManager.Level.WARN, String.Format("Error Loading Card ID: {0} - Type {1} not supported.",
                            c.Attribute("id").Value, c.Attribute("type").Value), "LoadCardDatabase");
                    }
                }
                catch (System.Exception exc)
                {
                    string message = exc.Message;
                    LogManager.Write(LogManager.Level.WARN, String.Format("Error Loading Card ID: {0} - {1}",
                        c.Attribute("id").Value, exc.Message), "LoadCardDatabase");
                }
                docNum++;
            }
            
            return Cards;
        }

        private static Card CreateNewCardObject(XElement cardNode)
        {
            string cardType = cardNode.Attribute("type").Value;
            Card card = default(Card);
            try
            {
                switch (cardType)
                {
                    case "action":
                        card = new Strategy(cardNode);
                        //Cards.Add(cardID, new Strategy(cardNode));
                        break;
                    case "ancestor":
                        card = new Ancestor(cardNode);
                        break;
                    case "celestial":
                        card = new Celestial(cardNode);
                        //Cards.Add(cardID, new Celestial(cardNode));
                        break;
                    case "event":
                        card = new Event(cardNode);
                        //Cards.Add(cardID, new Event(cardNode));
                        break;
                    case "follower":
                        card = new Follower(cardNode);
                        //Cards.Add(cardID, new Follower(cardNode));
                        break;
                    case "holding":
                        card = new Holding(cardNode);
                        //Cards.Add(cardID, new Holding(cardNode));
                        break;
                    case "item":
                        card = new Item(cardNode);
                        //Cards.Add(cardID, new Item(cardNode));
                        break;
                    case "personality":
                        card = new Personality(cardNode);
                        //Cards.Add(cardID, new Personality(cardNode));
                        break;
                    case "region":
                        card = new Region(cardNode);
                        //Cards.Add(cardID, new Region(cardNode));
                        break;
                    case "ring":
                        card = new Ring(cardNode);
                        //Cards.Add(cardID, new Ring(cardNode));
                        break;
                    case "spell":
                        card = new Spell(cardNode);
                        //Cards.Add(cardID, new Spell(cardNode));
                        break;
                    case "sensei":
                        card = new Sensei(cardNode);
                        break;
                    case "strategy":
                        card = new Strategy(cardNode);
                        //Cards.Add(cardID, new Strategy(cardNode));
                        break;
                    case "stronghold":
                        card = new Stronghold(cardNode);
                        //Cards.Add(cardID, new Stronghold(cardNode));
                        break;
                    case "wind":
                        card = new Wind(cardNode);
                        break;
                }
            }
            catch (Exception e)
            {
                string message = e.Message;
                throw;
            }
            return card;
        }

        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public static Card FindCardByID(string CardID)
        {
            return _cardDictionary[CardID];
        }

        public static Card FindCardByName(string CardName)
        {
            var card = (from selectCard in _cardDictionary
                         where selectCard.Value.Name == CardName
                         select selectCard.Value);

            return (Card)card.First();
        }

        #endregion Methods
    }
}